package org.micode.libs.dao.base;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.micode.common.domain.DataPage;
import org.micode.common.domain.Page;
import org.micode.common.domain.base.BaseEntity;
import org.micode.common.domain.base.BaseQuery;
import org.micode.common.utils.BeanExtUtils;
import org.micode.common.utils.StringExtUtils;

import java.util.List;
import java.util.Map;

/**
 * 服务类,基本方法
 */
@Slf4j
public abstract class BaseInitServiceImpl
        <KT, DTO extends BaseEntity<KT>, DO extends BaseEntity<KT>,
                QY extends BaseQuery<DO>, DAO extends BaseInitDao<DTO>>
        implements BaseInitService<KT, DTO, QY> {

    protected abstract DAO getMyDao();

    public BaseInitServiceImpl() {
        super();
    }

    protected String getOrderByString(Map<String, String> orderMap) {
        if (null == orderMap) {
            return null;
        }

        StringBuilder ret = new StringBuilder();
        for (String key : orderMap.keySet()) {
            String sortFlag = orderMap.get(key);
            if (StringUtils.isEmpty(key)) {
                continue;
            } else if (StringUtils.isEmpty(sortFlag)) {
                sortFlag = "ASC";
            }

            ret.append(", ").append(key).append(" ").append(sortFlag);
        }

        String orderBy = ret.toString();
        if (StringUtils.isEmpty(orderBy)) {
            return null;
        }

        return orderBy.substring(1);
    }

    protected long innerCountByQuery(QY dataQuery) {
        Map<String, Object> queryConditions = dataQuery.getConditionMap();
        List<String> extConditions = dataQuery.getExtConditions();
        log.trace("countByQuery() queryConditions：{}, extConditions: {}",
                StringExtUtils.mapToString(queryConditions),
                StringExtUtils.listToString(extConditions)
        );
        List<Long> ret = getMyDao().countByConditions(queryConditions, extConditions);
        if (null != ret && ret.size() > 0 && null != ret.get(0)) {
            return ret.get(0);
        }
        return 0;
    }

    protected List<DTO> listByQueryInner(QY dataQuery, String orderString) {
        Map<String, Object> queryConditions = dataQuery.getConditionMap();
        List<String> extConditions = dataQuery.getExtConditions();
        log.trace("listByQueryInner() queryConditions：{}, extConditions: {}",
                StringExtUtils.mapToString(queryConditions),
                StringExtUtils.listToString(extConditions)
        );
        return getMyDao().listByConditions(
                queryConditions, extConditions,
                dataQuery.getPage(), orderString);
    }

    @Override
    public DataPage<DTO> listPage(QY dataQuery) {
        return listPageInner(dataQuery, null);
    }

    @Override
    public DataPage<DTO> listPage(QY dataQuery, Map<String, String> orderMap) {
        String orderBy = getOrderByString(orderMap);
        return listPageInner(dataQuery, orderBy);
    }

    private DataPage<DTO> listPageInner(QY dataQuery, String orderString) {
        DataPage<DTO> ret = new DataPage<>();

        ret.setList(listByQueryInner(dataQuery, orderString));

        Page page = BeanExtUtils.copyObject(dataQuery.getPage(), Page.class);
        if (page.getPageNo() <= 1) {
            page.setDataCount(innerCountByQuery(dataQuery));
        }
        ret.setPage(page);

        return ret;
    }

    @Override
    public DTO getByKey(DTO example) {
        if (null == example.getKeyValue()) {
            return null;
        }
        return get(example.getKeyValue());
    }

    @Override
    public DTO get(KT key) {
        return getMyDao().getByKey(key);
    }

}
